package com.dounine.clouddisk360.store;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Consts;
import org.apache.http.client.CookieStore;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.cookie.BasicClientCookie2;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONReader;
import com.alibaba.fastjson.JSONWriter;
import com.dounine.clouddisk360.parser.deserializer.BaseConst;

public class CookieStoreUT {

	private static final Logger LOGGER = LoggerFactory.getLogger(CookieStoreUT.class);
	
	private static final String COOKIE_STORE_PATH = "cookieStore/";

	private CookieStoreUT() {
	}

	private static CookieStoreUT cookieStoreUT = new CookieStoreUT();

	private String basePath;
	private static CookieStore cookieStore;

	public static CookieStoreUT getInstance() {
		return cookieStoreUT;
	}

	public void writeCookieStoreToDisk(String savePath, CookieStore cookieStore, String[] filterCookies) {
		writeCookiesToDisk(cookieStore.getCookies(), filterCookies, true);
	}

	public void writeCookieStoreToDisk(String savePath, CookieStore cookieStore, String[] filterCookies,
			boolean converCookieStore) {
		writeCookiesToDisk(cookieStore.getCookies(), filterCookies, converCookieStore);
	}

	public CookieStore readCookieStoreForDisk(String[] filterCookies) {
		if (null != cookieStore)
			return cookieStore;
		if (null == filterCookies)
			filterCookies = new String[0];
		List<BasicCookieStore3> cookies = new ArrayList<>(0);
		File cookiesFile = new File(basePath + COOKIE_STORE_PATH + BaseConst.COOKIES_PATH_NAME);
		try {
			if (!cookiesFile.exists()) {
				cookiesFile.getParentFile().mkdirs();
				cookiesFile.createNewFile();
				LOGGER.info(BaseConst.COOKIES_PATH_NAME + "文件不存在,主动创建一个空文件,返回新创建的BasiccookieStore");
				return new BasicCookieStore();
			}
			if(StringUtils.isBlank(FileUtils.readFileToString(cookiesFile, "utf-8"))){
				LOGGER.warn("cookieStore文件内容为空");
				return new BasicCookieStore();
			}
			JSONReader reader = new JSONReader(new FileReader(cookiesFile));
			reader.startArray();
			while (reader.hasNext()) {
				cookies.add(reader.readObject(BasicCookieStore3.class));
			}
			reader.endArray();
			reader.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		List<Cookie> appacheCookies = new ArrayList<>(cookies.size());
		BasicClientCookie2 cookie2 = null;
		for (BasicCookieStore3 cookieStore3 : cookies) {
			cookie2 = new BasicClientCookie2(cookieStore3.getName(), cookieStore3.getValue());
			cookie2.setCreationDate(cookieStore3.getCreationDate());
			cookie2.setDomain(cookieStore3.getDomain());
			cookie2.setExpiryDate(cookieStore3.getExpiryDate());
			cookie2.setPath(cookieStore3.getPath());
			cookie2.setSecure(cookieStore3.getSecure());
			cookie2.setVersion(cookieStore3.getVersion());
			appacheCookies.add(cookie2);
		}
		List<Cookie> filterCookieLists = new ArrayList<>(appacheCookies.size());
		for (Cookie cookie : appacheCookies) {
			boolean isFilter = false;
			if (filterCookies.length == 0) {
				isFilter = true;
			} else {
				for (String cookieName : filterCookies) {
					if (cookie.getName().equals(cookieName)) {
						isFilter = true;
						break;
					}
				}
			}
			if (isFilter) {
				filterCookieLists.add(cookie);
			}
		}
		return new CookieStore() {

			@Override
			public List<Cookie> getCookies() {
				return filterCookieLists;
			}

			@Override
			public boolean clearExpired(Date date) {
				return false;
			}

			@Override
			public void clear() {
				filterCookieLists.clear();
			}

			@Override
			public void addCookie(Cookie cookie) {
				filterCookieLists.add(cookie);
			}
		};
	}

	public CookieStore readCookieStoreForDisk() {
		return readCookieStoreForDisk(null);
	}

	private void writeCookiesToDisk(List<Cookie> responseCookies, String[] filterCookies, boolean converCookieStore) {
		if (null == filterCookies) {
			filterCookies = new String[0];// 手动初始化,防止异常
		}
		if (CollectionUtils.isNotEmpty(responseCookies)) {
			List<Cookie> writeDiskCookies = new ArrayList<>(0);

			List<Cookie> readDiskCookies = readCookieStoreForDisk().getCookies();// 读取磁盘上的cookies缓存

			if (converCookieStore) {
				for (Cookie responseCookie : responseCookies) {
					if (filterCookies.length == 0) {
						writeDiskCookies.add(responseCookie);
					} else {
						for (String cookieName : filterCookies) {
							if (responseCookie.getName().equals(cookieName)) {
								writeDiskCookies.add(responseCookie);
								break;
							}
						}
					}
				}
				for (Cookie diskCookie : readDiskCookies) {
					if (false == writeDiskCookies.stream().anyMatch(c -> c.getName().equals(diskCookie.getName()))) {// 把不存在的cookie重新添加回去
						writeDiskCookies.add(diskCookie);
					}
				}
			} else {
				writeDiskCookies = new ArrayList<>(readDiskCookies);
				for (Cookie responseCookie : responseCookies) {
					if (false == readDiskCookies.stream().anyMatch(c -> c.getName().equals(responseCookie.getName()))) {// 把新的cookie添加进去
						if (filterCookies.length == 0) {
							writeDiskCookies.add(responseCookie);
						} else {
							for (String cookieName : filterCookies) {
								if (responseCookie.getName().equals(cookieName)) {
									writeDiskCookies.add(responseCookie);
									break;
								}
							}
						}
					}
				}
			}

			File cookiesFile = new File(basePath + COOKIE_STORE_PATH + BaseConst.COOKIES_PATH_NAME);

			try {
				if (!cookiesFile.exists()) {
					cookiesFile.getParentFile().mkdirs();
				}
				JSONWriter writer = new JSONWriter(new FileWriter(cookiesFile));
				writer.startArray();
				writeDiskCookies.forEach(writer::writeObject);
				writer.endArray();
				writer.flush();
				writer.close();
				cookieStore = new BasicCookieStore();
				cookieStore.getCookies().clear();
				cookieStore.getCookies().addAll(writeDiskCookies);
				LOGGER.info(String.format("360云盘登录cookies保存路径 [ %s ] ", cookiesFile.getAbsolutePath()));
			} catch (FileNotFoundException e) {
				LOGGER.error("cookies文件找不到");
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public void writeCookieStoreToDisk(CookieStore cookieStore, boolean converCookieStore) {
		writeCookiesToDisk(cookieStore.getCookies(), null, converCookieStore);
	}

	public String getBasePath() {
		return basePath;
	}

	public void setBasePath(String basePath) {
		this.basePath = basePath;
	}

}
